package com.uraurora.crescent.util;

import com.google.common.cache.Cache;
import com.uraurora.crescent.function.*;
import com.uraurora.crescent.function.functools.memoizer.*;
import com.uraurora.crescent.tuple.ITuple;

import java.util.concurrent.Future;

public final class Decorators {

    private Decorators(){}

    //<editor-fold desc="返回函数自身的函数装饰器，附加记忆化等方法">
    public static <T, RT> Func1<T, RT> decorate(Func1<T, RT> decorated){
        return decorated;
    }

    public static <T1, T2, RT> Func2<T1, T2, RT> decorate(Func2<T1, T2, RT> decorated){
        return decorated;
    }

    public static <T1, T2, T3, RT> Func3<T1, T2, T3, RT> decorate(Func3<T1, T2, T3, RT> decorated){
        return decorated;
    }

    public static <T1, T2, T3, T4, RT> Func4<T1, T2, T3, T4, RT> decorate(Func4<T1, T2, T3, T4, RT> decorated){
        return decorated;
    }

    public static <T1, T2, T3, T4, T5, RT> Func5<T1, T2, T3, T4, T5, RT> decorate(Func5<T1, T2, T3, T4, T5, RT> decorated){
        return decorated;
    }
    //</editor-fold>

    // TODO:装饰器

    //<editor-fold desc="memoize">
    
    public static <T, R> MemoizerFunc1<T, R> memoize(Func1<T, R> func){
        return new MemoizerFunc1<>(func);
    }

    public static <T1, T2, RT> MemoizerFunc2<T1, T2, RT> memoize(Func2<T1, T2, RT> func){
        return new MemoizerFunc2<>(func);
    }

    public static <T1, T2, T3, RT> MemoizerFunc3<T1, T2, T3, RT> memoize(Func3<T1, T2, T3, RT> func){
        return new MemoizerFunc3<>(func);
    }

    public static <T1, T2, T3, T4, RT> MemoizerFunc4<T1, T2, T3, T4, RT> memoize(Func4<T1, T2, T3, T4, RT> func){
        return new MemoizerFunc4<>(func);
    }

    public static <T1, T2, T3, T4, T5, RT> MemoizerFunc5<T1, T2, T3, T4, T5, RT> memoize(Func5<T1, T2, T3, T4, T5, RT> func){
        return new MemoizerFunc5<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, RT> MemoizerFunc6<T1, T2, T3, T4, T5, T6, RT> memoize(Func6<T1, T2, T3, T4, T5, T6, RT> func){
        return new MemoizerFunc6<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, T7, RT> MemoizerFunc7<T1, T2, T3, T4, T5, T6, T7, RT> memoize(Func7<T1, T2, T3, T4, T5, T6, T7, RT> func){
        return new MemoizerFunc7<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, T7, T8, RT> MemoizerFunc8<T1, T2, T3, T4, T5, T6, T7, T8, RT> memoize(Func8<T1, T2, T3, T4, T5, T6, T7, T8, RT> func){
        return new MemoizerFunc8<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, T7, T8, T9, RT> MemoizerFunc9<T1, T2, T3, T4, T5, T6, T7, T8, T9, RT> memoize(Func9<T1, T2, T3, T4, T5, T6, T7, T8, T9, RT> func){
        return new MemoizerFunc9<>(func);
    }

    public static <T, R> MemoizerFunc1<T, R> memoize(Func1<T, R> func, Cache<ITuple, Future<R>> cache){
        return new MemoizerFunc1<>(func, cache);
    }

    public static <T1, T2, RT> MemoizerFunc2<T1, T2, RT> memoize(Func2<T1, T2, RT> func,
                                                            Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc2<>(func, cache);
    }

    public static <T1, T2, T3, RT> MemoizerFunc3<T1, T2, T3, RT> memoize(Func3<T1, T2, T3, RT> func,
                                                                    Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc3<>(func, cache);
    }

    public static <T1, T2, T3, T4, RT> MemoizerFunc4<T1, T2, T3, T4, RT> memoize(Func4<T1, T2, T3, T4, RT> func,
                                                                            Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc4<>(func, cache);
    }

    public static <T1, T2, T3, T4, T5, RT> MemoizerFunc5<T1, T2, T3, T4, T5, RT> memoize(Func5<T1, T2, T3, T4, T5, RT> func,
                                                                                    Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc5<>(func, cache);
    }

    public static <T1, T2, T3, T4, T5, T6, RT> MemoizerFunc6<T1, T2, T3, T4, T5, T6, RT> memoize(Func6<T1, T2, T3, T4, T5, T6, RT> func,
                                                                                                 Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc6<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, T7, RT> MemoizerFunc7<T1, T2, T3, T4, T5, T6, T7, RT> memoize(Func7<T1, T2, T3, T4, T5, T6, T7, RT> func,
                                                                                                         Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc7<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, T7, T8, RT> MemoizerFunc8<T1, T2, T3, T4, T5, T6, T7, T8, RT> memoize(Func8<T1, T2, T3, T4, T5, T6, T7, T8, RT> func,
                                                                                                                 Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc8<>(func);
    }

    public static <T1, T2, T3, T4, T5, T6, T7, T8, T9, RT> MemoizerFunc9<T1, T2, T3, T4, T5, T6, T7, T8, T9, RT> memoize(Func9<T1, T2, T3, T4, T5, T6, T7, T8, T9, RT> func,
                                                                                                                         Cache<ITuple, Future<RT>> cache){
        return new MemoizerFunc9<>(func);
    }
    //</editor-fold>




}
